package org.ethan.lyl.controller;

import br.com.objectos.core.lang.Preconditions;
import com.alibaba.fastjson.JSON;
import org.ethan.lyl.ImgAnalysis;
import org.ethan.lyl.PathAnalysis;
import org.ethan.lyl.Screenshot;
import org.ethan.lyl.StatusDailog;
import org.ethan.lyl.util.Path;
import org.ethan.lyl.util.ResultDto;
import org.ethan.lyl.util.StaticParams;
import org.ethan.lyl.util.StaticStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Author:Eason Lau
 * @Date:2018/10/31
 * @Description:
 */
@RestController
@RequestMapping("script")
public class ScriptController {

    @RequestMapping("run")
    public ResultDto run(HttpServletRequest request) {
        try {
            StaticParams.setTotalTimes(Integer.parseInt(request.getParameter("totalTimes")));
            StaticParams.setTrimming(Integer.parseInt(request.getParameter("trimming")));
            StaticParams.startSection = Integer.parseInt(request.getParameter("startSection"));
            StaticParams.closeGiftCoordinate = null;
            StaticParams.nextSectionCoordinate = null;
            StaticParams.running = true;
            StaticStatus.track = new ArrayList<>();
            new Thread(() -> {
                if (StaticParams.isRunning()) {
                    try {
                        for (StaticStatus.currentTimes = 0; StaticStatus.currentTimes < StaticParams.totalTimes && StaticParams.running; StaticStatus.currentTimes++) {
                            Date startTime = new Date();
                            Date excuteStartTime;
                            synchronized (StaticStatus.track) {
                                StatusDailog.setDailog(String.format("%d-running", StaticStatus.currentTimes+StaticParams.startSection));
                                StaticStatus.track.add("status:sectionStart");
                                StaticStatus.track.add(String.format("msg:第%d关", StaticStatus.currentTimes+StaticParams.startSection));
                                StaticStatus.track.add(String.format("cardNum:%d", StaticStatus.currentTimes+StaticParams.startSection));
                                StaticStatus.track.add(String.format("msg:开始截屏", StaticStatus.currentTimes));
                            }
                            excuteStartTime = new Date();
                            String screenshotPath = Screenshot.screenshotByADB();
                            System.out.println(String.format("msg:截屏耗时:%d毫秒",new Date().getTime()-excuteStartTime.getTime()));

                            Preconditions.checkArgument(screenshotPath != null, "截屏失败");
                            synchronized (StaticStatus.track) {
                                StaticStatus.track.add(String.format("msg:开始分析二维数组", StaticStatus.currentTimes));
                            }
                            excuteStartTime = new Date();
                            ImgAnalysis.Coordinate[][] array = ImgAnalysis.getArray(screenshotPath);
                            StaticStatus.track.add("nativeArray:"+JSON.toJSONString(array));
                            System.out.println(String.format("分析数组耗时:%d毫秒",new Date().getTime()-excuteStartTime.getTime()));

                            Preconditions.checkArgument(array != null, "数组分析失败");
                            synchronized (StaticStatus.track) {
                                StaticStatus.track.add(String.format("msg:开始计算路径", StaticStatus.currentTimes));
                            }
                            excuteStartTime = new Date();
                            List<PathAnalysis.ArrayIndex> pathArray = PathAnalysis.getPath(array);
                            StaticStatus.track.add("pathList:"+JSON.toJSONString(pathArray));
                            System.out.println(String.format("分析路径耗时:%d毫秒",new Date().getTime()-excuteStartTime.getTime()));
                            synchronized (StaticStatus.track) {
                                StaticStatus.track.add(String.format("msg:开始画线", StaticStatus.currentTimes));
                            }
                            String path = Path.SysPath();
                            File adbDir = new File(path + "adb");
                            Runtime rt = Runtime.getRuntime();
                            excuteStartTime = new Date();
                            //画线
                            for (int i = 0; i < pathArray.size() - 1; i++) {
                                String cmd = String.format("cmd.exe /c " + adbDir + "/adb shell input swipe %d %d %d %d 200",
                                        array[pathArray.get(i).i][pathArray.get(i).j].X,
                                        array[pathArray.get(i).i][pathArray.get(i).j].Y,
                                        array[pathArray.get(i + 1).i][pathArray.get(i + 1).j].X,
                                        array[pathArray.get(i + 1).i][pathArray.get(i + 1).j].Y
                                );
                                Process process = rt.exec(cmd);
                                //经常失效，故多画一次
                                if( i == pathArray.size() - 2){
                                    Thread.sleep(250);
                                    cmd = String.format("cmd.exe /c " + adbDir + "/adb shell input swipe %d %d %d %d 200",
                                            array[pathArray.get(i).i][pathArray.get(i).j].X,
                                            array[pathArray.get(i).i][pathArray.get(i).j].Y,
                                            array[pathArray.get(i + 1).i][pathArray.get(i + 1).j].X,
                                            array[pathArray.get(i + 1).i][pathArray.get(i + 1).j].Y
                                    );
                                    process = rt.exec(cmd);
                                    process.waitFor();
                                }

                                synchronized (StaticStatus.track) {
                                    StaticStatus.track.add(String.format("percent:%.0f", new BigDecimal((float)i+2).divide(new BigDecimal((float)pathArray.size()),2,BigDecimal.ROUND_UP).floatValue()*100));
                                }
                                Thread.sleep(250);

                                //process.waitFor();
                            }
                            System.out.println(String.format("画图耗时:%d毫秒",new Date().getTime()-excuteStartTime.getTime()));

                            rt.freeMemory();
                            Thread.sleep(1500);
                            synchronized (StaticStatus.track) {
                                StaticStatus.track.add(String.format("====关闭领取礼物弹出框====", StaticStatus.currentTimes));
                            }
                            //领取礼物关
                            if((StaticParams.startSection+StaticStatus.currentTimes)%5==0){
                                Thread.sleep(1000);
                                //坐标未存在
                                if(StaticParams.closeGiftCoordinate==null){
                                    BufferedImage binaryImage = ImgAnalysis.binaryImage(ImageIO.read(new FileInputStream(Screenshot.screenshotByADB())));
                                    ImageIO.write(binaryImage,"JPG",new File(Path.SysPath()+"/screenshot/closeGift.jpg"));
                                    ImgAnalysis.Coordinate closeGiftCoodinate = ImgAnalysis.getCloseGifeCoodinate(binaryImage);
                                    StaticParams.closeGiftCoordinate = closeGiftCoodinate.X + " " + closeGiftCoodinate.Y;
                                }
                                Process process = rt.exec("cmd.exe /c "+adbDir+"/adb shell input tap "+StaticParams.closeGiftCoordinate);
                                process.waitFor();
                                Thread.sleep(1500);
                            }

                            synchronized (StaticStatus.track) {
                                StaticStatus.track.add(String.format("====进入下一关====", StaticStatus.currentTimes));
                            }

                            //坐标未存在
                            if(StaticParams.nextSectionCoordinate==null){
                                BufferedImage binaryImage = ImgAnalysis.binaryImage(ImageIO.read(new FileInputStream(Screenshot.screenshotByADB())));
                                ImageIO.write(binaryImage,"JPG",new File(Path.SysPath()+"/screenshot/nextLevel.jpg"));
                                ImgAnalysis.Coordinate nextLevelCoodinate = ImgAnalysis.getNextLevelCoodinate(binaryImage);
                                StaticParams.nextSectionCoordinate = nextLevelCoodinate.X + " " + nextLevelCoodinate.Y;
                            }
                            Process process = rt.exec("cmd.exe /c "+adbDir+"/adb shell input tap " + StaticParams.nextSectionCoordinate);
                            process.waitFor();
                            Thread.sleep(1500);
                            synchronized (StaticStatus.track) {
                                StaticStatus.track.add(String.format("msg:耗时%ds", (new Date().getTime() - startTime.getTime()) / 1000));
                                StaticStatus.track.add("status:sectionStop");
                            }
                        }

                        StatusDailog.setDailog("programStop");
                        synchronized (StaticStatus.track) {

                            StaticStatus.track.add(String.format("msg:程序结束"));
                            StaticStatus.track.add("status:programStop");
                            StaticParams.running = false;
                            StaticStatus.currentTimes = 0;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        StatusDailog.setDailog("errorProgramStop");
                        synchronized (StaticStatus.track) {
                            StaticStatus.track.add(String.format("msg:异常，程序终止（%s）", e.getMessage()));
                            StaticStatus.track.add("status:programStop");
                        }
                    }
                }
            }).start();
            return ResultDto.success();
        } catch (Exception e) {
            e.printStackTrace();
            return ResultDto.fail(e.getMessage());
        }
    }
    @RequestMapping("stop")
    public ResultDto stop(HttpServletRequest request) {
        try {
            StaticParams.running = false;
            return ResultDto.success();
        } catch (Exception e) {
            e.printStackTrace();
            return ResultDto.fail(e.getMessage());
        }
    }

    @RequestMapping("getTrack")
    public String getTrack() {
        try {
            String track;
            synchronized (StaticStatus.track){
                track = JSON.toJSONString(StaticStatus.track);
                StaticStatus.track = new ArrayList<>();
            }
            return track;
        } catch (Exception e) {
            e.printStackTrace();
            return JSON.toJSONString(new ArrayList<>());
        }
    }

}
